/*
 * Project Name: CZW_PRO
 * File Name: ZipUtils.java
 * Copyright: Copyright(C) 1985-2014 ZKTeco Inc. All rights reserved.
 */
package com.xdtech.common.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;

/**
 * 压缩工具
 * 
 * @author <a href="max.zheng@zkteco.com">郑志雄</>
 * @version TODO 添加版本
 * @see 相关类或方法，不需要请删除此行
 * @since 2014-12-4 下午3:29:25
 */
public class ZipUtils
{

	/**
	 * 使用GBK编码可以避免压缩中文文件名乱码
	 */
	private static final String CHINESE_CHARSET = "GBK";

	/**
	 * 文件读取缓冲区大小
	 */
	private static final int CACHE_SIZE = 1024;

	/**
	 * <p>
	 * 压缩文件
	 * </p>
	 * 
	 * @param sourceFolder 压缩文件夹
	 * @param zipFilePath 压缩文件输出路径
	 * @throws Exception
	 */
	public static boolean zip(String sourceFolder, String zipFilePath) 
	{
		boolean rs = true;
		try
		{
			OutputStream out = new FileOutputStream(zipFilePath);
			BufferedOutputStream bos = new BufferedOutputStream(out);
			ZipOutputStream zos = new ZipOutputStream(bos);
			// 解决中文文件名乱码
			zos.setEncoding(CHINESE_CHARSET);
			File file = new File(sourceFolder);
			String basePath = null;
			if (file.isDirectory())
			{
				basePath = file.getPath();
			}
			else
			{
				basePath = file.getParent();
			}
			zipFile(file, basePath, zos);
			zos.closeEntry();
			zos.close();
			bos.close();
			out.close();
		}catch (Exception e){
			e.printStackTrace();
			rs =  false;
		}finally {
			
		}
		return rs;
	}

	/**
	 * <p>
	 * 递归压缩文件
	 * </p>
	 * 
	 * @param parentFile
	 * @param basePath
	 * @param zos
	 * @throws Exception
	 */
	private static void zipFile(File parentFile, String basePath, ZipOutputStream zos) throws Exception
	{
		File[] files = new File[0];
		if (parentFile.isDirectory())
		{
			files = parentFile.listFiles();
		}
		else
		{
			files = new File[1];
			files[0] = parentFile;
		}
		String pathName;
		InputStream is;
		BufferedInputStream bis;
		byte[] cache = new byte[CACHE_SIZE];
		for (File file : files)
		{
			if (file.isDirectory())
			{
				pathName = file.getPath().substring(basePath.length() + 1) + "/";
				zos.putNextEntry(new ZipEntry(pathName));
				zipFile(file, basePath, zos);
			}
			else
			{
				pathName = file.getPath().substring(basePath.length() + 1);
				is = new FileInputStream(file);
				bis = new BufferedInputStream(is);
				zos.putNextEntry(new ZipEntry(pathName));
				int nRead = 0;
				while ((nRead = bis.read(cache, 0, CACHE_SIZE)) != -1)
				{
					zos.write(cache, 0, nRead);
				}
				bis.close();
				is.close();
			}
		}
	}

	/**
	 * <p>
	 * 解压压缩包
	 * </p>
	 * 
	 * @param zipFilePath 压缩文件路径
	 * @param destDir 压缩包释放目录
	 * @throws Exception
	 */
	public static void unZip(String zipFilePath, String destDir) throws Exception
	{
		ZipFile zipFile = new ZipFile(zipFilePath, CHINESE_CHARSET);
		Enumeration<?> emu = zipFile.getEntries();
		BufferedInputStream bis;
		FileOutputStream fos;
		BufferedOutputStream bos;
		File file, parentFile;
		ZipEntry entry;
		byte[] cache = new byte[CACHE_SIZE];
		while (emu.hasMoreElements())
		{
			entry = (ZipEntry) emu.nextElement();
			if (entry.isDirectory())
			{
				new File(destDir + entry.getName()).mkdirs();
				continue;
			}
			bis = new BufferedInputStream(zipFile.getInputStream(entry));
			file = new File(destDir + entry.getName());
			parentFile = file.getParentFile();
			if (parentFile != null && (!parentFile.exists()))
			{
				parentFile.mkdirs();
			}
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos, CACHE_SIZE);
			int nRead = 0;
			while ((nRead = bis.read(cache, 0, CACHE_SIZE)) != -1)
			{
				fos.write(cache, 0, nRead);
			}
			bos.flush();
			bos.close();
			fos.close();
			bis.close();
		}
		zipFile.close();
	}

	public static void main(String[] args) throws Exception
	{
		String sourceFolder = "D:/压缩文件夹";
		String zipFilePath = "D:/压缩包.zip";
		String destDir = "D:/";
		ZipUtils.zip(sourceFolder, zipFilePath);
		ZipUtils.unZip(zipFilePath, destDir);
	}
}
